/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package apus.command.account;

import apus.command.AbstractCommand;
import apus.command.period.AddPeriodCommand;
import apus.entity.Account;
import apus.entity.Period;
import apus.entity.RealAccount;
import apus.entity.Subscriber;
import apus.exception.BusinessException;
import apus.exception.EntityNotFoundException;
import apus.persistence.*;
import apus.services.ServiceLocator;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.List;

/**
 * The <code>AddAccountCommand</code> class represents command, which adds account
 * for subscriber.
 * @author  Maxim Vasilevsky
 * @author  Roman Dyatkovsky
 * @since APUS v0.3
 * @see AbstractCommand
 */
public class AddAccountCommand <TypeEn extends Subscriber, TypeDAO extends AbstractDAO<TypeEn>> extends AbstractCommand{
    
    private Class<TypeDAO> clazz;
    
    private final static String PARAM_SUBSCRIBER_ID = "Subscriber id";
    private final static String PARAM_START_DATE = "Start date";
    private final static String PARAM_END_DATE = "End date";
    
    
    private final static String[] paramsNames = { PARAM_SUBSCRIBER_ID, 
                                                  PARAM_START_DATE,
                                                  PARAM_END_DATE};
    
    
    public AddAccountCommand(Class<TypeDAO> clazz, String name) {
        super(name);
        this.clazz = clazz;
    }

    @Override
    public void execute(){
        int ID;
        String stringId = params.get(PARAM_SUBSCRIBER_ID);
        
        try{
            ID = Integer.parseInt(stringId);
        } catch (NumberFormatException e){
            throw new BusinessException("Wrong ID format: "+stringId, e);
        }
        
        AccountDAO accountDAO = ServiceLocator.getService(AccountDAO.class);
        AbstractDAO<TypeEn> DAO = ServiceLocator.getService(clazz);
        PeriodDAO periodDAO = ServiceLocator.getService(PeriodDAO.class);
        Subscriber subscriber = DAO.read(ID);
        
        if (subscriber==null) {
            throw new BusinessException("Subscriber not found");
        }
        
        DateFormat df = DateFormat.getDateInstance();
        Period period=null;
        
        try {
            period = periodDAO.readByStartAndEndDates(df.parse(params.get(PARAM_START_DATE)),df.parse(params.get(PARAM_END_DATE)));
        } catch (ParseException ex) {
            throw new BusinessException("Wrong date format.", ex);
        } catch (EntityNotFoundException e) {
            System.out.println(e.getMessage()+ " Creating new period..");
        }
        
        if (period==null){      
            
            AddPeriodCommand adp=new AddPeriodCommand();
            for(String paramName : adp.getParamNames()) {
                String paramValue = params.get(paramName);
                adp.setParameter(paramName, paramValue);
            }
            adp.execute();
        }
        
        try {
            period = periodDAO.readByStartAndEndDates(df.parse(params.get(PARAM_START_DATE)),df.parse(params.get(PARAM_END_DATE)));
        } catch (ParseException ex) {
            throw new BusinessException("Wrong date format.", ex);
        }
        
        Account newAccount = new RealAccount(subscriber,period);
        newAccount.calculate();
        accountDAO.create(newAccount);
    }

    @Override
    public List<String> getParamNames() {
        return Arrays.asList(paramsNames);
    }
    
    public static AddAccountCommand getAddAccountForPersonCommand() {
        return new AddAccountCommand(PersonDAO.class, "Create account for person");
    }
    
    public static AddAccountCommand getAddAccountForOrganizationCommand() {
        return new AddAccountCommand(OrganizationDAO.class, "Create account for organization");
    }
    
    
    
}